#pragma once

/*=================================================================================================

Sposob uzycia:
1. Dodac obiekt Hang<T> do klasy T
2. Zadeklarowac jakikolwiek wieszak Hanger<T>
3. Zawiesic obiekt na wieszaku:
	- funkcja:				Hang::attach(Hanger<T>* hanger)
	- poprzez konstruktor:	Hang::Hang(T *element, Hanger<T>* hanger=0)

=================================================================================================*/

template <class T> class Hang;

template <class T> 
class Hanger
{
public:
	~Hanger()
	{
		clear();
	}

	u32 size()
	{
		return m_vec.size();
	}

	T* operator[] (u32 index)
	{
		if(index >= size())
			return 0;
		return m_vec[index]->get();
	}

	void clear()
	{
		while(size()>0)
			m_vec[0]->detach();
	}

private:
	std::vector<Hang<T>*> m_vec;

	friend class Hang<T>;
};

template <class T>
class Hang
{
public:

	Hang(T *element, Hanger<T>* hanger=0): m_vec(0), m_element(element)
	{
		if(hanger) attach(hanger);
	}
	~Hang()
	{
		detach();
	}
	T *get()
	{
		return m_element;
	}

	void attach(Hanger<T>* hanger)
	{
		if(m_vec) detach();

		if(hanger) m_vec = &hanger->m_vec;
		else return;

		m_id = m_vec->size();
		m_vec->push_back(this);
	}

	void detach()
	{
		if(m_vec==0) return;

		Hang<T> *replaced = (*m_vec)[m_vec->size()-1];
		replaced->m_id = m_id;
		(*m_vec)[m_id] = replaced;
		m_vec->pop_back();

		m_vec = 0;
	}
private:
	u32						m_id;
	std::vector<Hang<T>*>*	m_vec;
	T*						m_element;
};